/**
 * Created Date: Monday, July 17th 2023, 11:01:17 pm
 * Author: CodingGorit
 * -----
 * Last Modified: Sun Jul 23 2023
 * Modified By: CodingGorit
 * -----
 * Copyright © 2019 —— 2023 fmin-courses TP Center All Rights Reserved
 * ------------------------------------
 * Javascript will save your soul!
 */

"use strict";
import EventEmitter from "events";
import Utils from '../utils/Utils';
import log from '../utils/log';
import { IQiniuConfig, IUploadCallback } from "../types";
const qiniu = require("qiniu");

const TAG = "OssManager";

export type OssType = "qiniu-oss" | "aliyun-oss" | "tencent-oss";


class OssManager {

    private static _instance: OssManager;
    private _accessKey: string;
    private _accessSecret: string;
    private _bucketName: string;
    private _baseRoot: string;
    private _updateToken: string;
    private _ossConfig: any;
    private _readyToUpload: boolean;

    public static getInstance(ossType: OssType = "qiniu-oss") {
        if (!this._instance) { 
            this._instance = new OssManager(ossType);
        }
        return this._instance;
    }

    constructor(ossType: OssType) {
        const config = Utils.getInstance().getConfig("oss.qiniu") as IQiniuConfig;
        this._accessKey = config.accessKey;
        this._accessSecret = config.secretKey;
        this._bucketName = config.bucketName;
        this._baseRoot = config.baseRoot;
        this._updateToken = "";
        this._readyToUpload = false;
        this.initOssConfig(ossType);
    }


    private initOssConfig(ossType: OssType) {
        switch (ossType) {
            case "qiniu-oss": {
                const mac = new qiniu.auth.digest.Mac(this._accessKey, this._accessSecret);

                // 创建上传凭证
                const options = {
                    scope: this._bucketName,
                };
                const putPolicy = new qiniu.rs.PutPolicy(options);
                this._updateToken = putPolicy.uploadToken(mac);

                this._ossConfig = new qiniu.conf.Config();
                // 空间对应的机房 (当前算 华北)
                this._ossConfig.zone = qiniu.zone.Zone_z1;
                // 是否使用https域名
                // this._ossConfig.useHttpsDomain = true;
                // 上传是否使用cdn加速
                //config.useCdnDomain = true;
                this._readyToUpload = true;
                break;
            }
            case "aliyun-oss":
            case "tencent-oss":
                break;
            default:
                log.info(TAG, "Unknown type");
        }
    }

    /**
     * 七牛云本地文件上传
     * @param url 
     */
    public uploadFileWithLocal(fileName: string, url: string, callback: (resp: IUploadCallback) => void) {
        if (!this._readyToUpload || !this._ossConfig) {
            callback({
                state: "fail",
                data: null
            });
        }

        const formUploader = new qiniu.form_up.FormUploader(this._ossConfig);
        const putExtra = new qiniu.form_up.PutExtra();
        // 没有配置 baseRoot, 上传的就是 oss 根路径
        const key = this._baseRoot + fileName;
        // 文件上传
        formUploader.putFile(this._updateToken, key, url, putExtra, function (respErr,
            respBody, respInfo) {
            if (respErr) {
                throw respErr;
            }

            if (respInfo.statusCode === 200) {
                // console.log("-------" + respBody);
                callback({
                    state: "success",
                    data: respBody
                });
            } else {
                console.log(respInfo.statusCode);
                // console.log(respBody);
                callback({
                    state: "fail",
                    data: respBody
                });
            }
        });
    }

    // form 上传
    private uploadFileWithForm(key: string) {
        var config = new qiniu.conf.Config();
        // 空间对应的机房
        config.zone = qiniu.zone.Zone_z0;
        // 是否使用https域名
        //config.useHttpsDomain = true;
        // 上传是否使用cdn加速
        //config.useCdnDomain = true;

        var formUploader = new qiniu.form_up.FormUploader(config);
        var putExtra = new qiniu.form_up.PutExtra();
        var readableStream = "xxx"; // 可读的流
        formUploader.putStream(this._updateToken, key, readableStream, putExtra, function (respErr,
            respBody, respInfo) {
            if (respErr) {
                throw respErr;
            }

            if (respInfo.statusCode == 200) {
                console.log(respBody);
            } else {
                console.log(respInfo.statusCode);
                console.log(respBody);
            }
        });

    }
}

export default OssManager;